package com.example.demo.WebSocket;

import com.example.demo.server.UserMessageServer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 刘二朋
 * @date 2020-12-03 17:01
 */
@Component
@ServerEndpoint("/websocket/{uid}")
public class WebSocketServer {


    /**
     * 静态的MessageServer的对象
     */
    private static UserMessageServer userMessageServer;

    /**
     * 带一个参数的构造器
     *
     * @param messageServer 要进行初始化的对象
     */
    @Autowired
    public WebSocketServer(UserMessageServer messageServer) {
        this.userMessageServer = messageServer;
    }


    /**
     * 无参数的构造器
     */
    public WebSocketServer() {

    }

    //    存放所有登录的用户的账号 , 以及对应的Session对象
    public static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();

    /**
     * 与客户端建立连接 , 保存用户的账号 , 以及Session对象
     *
     * @param session Session对象
     * @param uid     要操作的用户
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) {
//        保存用户的账号 , 以及Session对象
        sessionPools.put(uid, session);
        System.out.println(uid + ": 已经成功的连接到服务器了----");
    }

    /**
     * 用户与服务端关闭连接 , 触发该方法
     *
     * @param uid 要断开连接的id
     */
    @OnClose
    public void onConse(@PathParam("uid") String uid) {
        sessionPools.remove(uid);
        //移除用户的Session对象
        System.out.println(uid + ": 关闭了连接");
    }


    /**
     * 接收到客户端的数据 , 调用此方法
     *
     * @param session Session对象
     * @param message 要接收到的数据
     */
    @OnMessage
    public void onMessage(Session session, String message) {
//        System.out.println("接收到的数据是 : " + message);
        //线程安全的
        synchronized (message) {
            //        创建ObjectMapper对象
            ObjectMapper objectMapper = new ObjectMapper();
            try {
//            方法重给定的JSON格式的字符串 , 反序列化json数据
                Map<String, Object> map = objectMapper.readValue(message, Map.class);
//                自动注入一个消息对象 , 并把消息 , 存放到数据库
                userMessageServer.addUserMessage(map.get("converid") + "", map.get("fromId") + "", map.get("toId") + "", map.get("type") + "", map.get("time") + "", map.get("content") + "");
//            给指定的用户 . 发送数据
                sendMessageToUser(map.get("toId") + "", message);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送消息
     *
     * @param session 接收消息的session
     * @param message 发送的消息
     */
    private static void sendMessage(Session session, String message) {
//            判断Session对象 , 是否为null
        if (session != null) {
            synchronized (session) {
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 给指定用户发送消息
     *
     * @param uid     接收消息的id
     * @param message 发送的消息
     */
    public static void sendMessageToUser(String uid, String message) {
        System.out.println("发送消息 , 进来了");
//        System.out.println("要发送的消息用户 : " + uid + "\n" + "要发送的消息内容 : " + message);
        if (sessionPools.containsKey(uid)) {
            Session session = sessionPools.get(uid);
            sendMessage(session, message);
        }
    }

    /**
     * 客户端出现异常 , 调用此方法 ,
     *
     * @param session   session对象
     * @param throwable 异常对象
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
//        出现异常 ,
        System.out.println(throwable.getMessage());
    }
}
